package vip.xiaonuo.dev.modular.wechat.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.util.CommonCryptogramUtil;
import vip.xiaonuo.common.util.CommonStringUtil;
import vip.xiaonuo.dev.api.DevConfigApi;
import vip.xiaonuo.dev.modular.wechat.enums.WechatUrlEnum;
import vip.xiaonuo.dev.modular.wechat.param.DevWechatParam;
import vip.xiaonuo.dev.modular.wechat.param.WechatConfigParam;
import vip.xiaonuo.dev.modular.wechat.param.wechatReq.*;
import vip.xiaonuo.dev.modular.wechat.param.wechatRes.WechatCalendarRes;
import vip.xiaonuo.dev.modular.wechat.param.wechatRes.WechatDepartmentRes;
import vip.xiaonuo.dev.modular.wechat.param.WechatTicketParam;
import vip.xiaonuo.dev.modular.wechat.param.WechatTokenParam;
import vip.xiaonuo.dev.modular.wechat.param.wechatRes.WechatScheduleRes;
import vip.xiaonuo.dev.modular.wechat.param.wechatRes.WechatUserRes;
import vip.xiaonuo.dev.modular.wechat.util.ase.AesException;
import vip.xiaonuo.dev.modular.wechat.util.ase.WXBizMsgCrypt;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author xsl
 * @date 2024-06-19 17:29
 **/
@Getter
@Setter
public class DevWechatUtil {

    private static Logger logger = LoggerFactory.getLogger(DevWechatUtil.class);

    /** 企业微信的过期时间 */
    private static long EXPIRES_TIME = 7100 ;

    private static String accessToken = "";

    private static String jsApiTicket = "";

    private WXBizMsgCrypt verifyClient = null;

    /** 配置企业微信的应用ID */
    // private static final String AGENT_ID = "1000004";
    private static final String AGENT_ID = "1000128";

    private static final String WECHAT_CORP_ID = "WECHAT_CORP_ID";

    private static final String WECHAT_CORP_SECRET = "WECHAT_CORP_SECRET";

    private static final String ENCODING_AES_KEY = "ENCODING_AES_KEY";

    private static final String WECHAT_TOKEN = "WECHAT_TOKEN";

    private static final String WECHAT_LOGIN_TOKEN = "WECHAT_TOKEN";
    


    public
    DevWechatUtil() {
        initWechat();
    }

    /**
     * 初始化操作的客户端,用以获取客户端
     *
     * @author xuyuxiang
     * @date 2022/1/5 23:24
     */
    private static void initWechat() {

        DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class);

        /* CORP_ID */
        String corpId = devConfigApi.getValueByKey(WECHAT_CORP_ID);

        if(ObjectUtil.isEmpty(corpId)) {
            throw new CommonException("企业微信客户端未正确配置：CORP_ID为空");
        }

        /* CORP_SECRET */
        String corpSecret = devConfigApi.getValueByKey(WECHAT_CORP_SECRET);

        if(ObjectUtil.isEmpty(corpSecret)) {
            throw new CommonException("企业微信客户端未正确配置：CORP_SECRET为空");
        }

        /* aesKey */
        String aesKey = devConfigApi.getValueByKey(ENCODING_AES_KEY);

        if(ObjectUtil.isEmpty(aesKey)) {
            throw new CommonException("企业微信客户端未正确配置：ENCODING_AES_KEY为空");
        }

        /* token */
        String token = devConfigApi.getValueByKey(WECHAT_TOKEN);

        if(ObjectUtil.isEmpty(token)) {
            throw new CommonException("企业微信客户端未正确配置：WECHAT_TOKEN为空");
        }

        try {
            DevWechatUtil.accessToken = devConfigApi.getWechatAccessToken();
            logger.info("accessToken 为：{}", accessToken);
            if(DevWechatUtil.accessToken.isEmpty()){
                logger.info("缓存accessToken不存在，重新请求access_token");
                Map<String, String> params = new HashMap<>();
                params.put("corpid", corpId);
                params.put("corpsecret", corpSecret);
                String res = WechatRequest.getMethod(WechatUrlEnum.BASE_URL.getValue(), params);
                ObjectMapper objectMapper = new ObjectMapper();
                WechatTokenParam wechatTokenParam = objectMapper.readValue(res, WechatTokenParam.class);
                if(!Objects.equals(wechatTokenParam.getErrcode(), "0")) throw new CommonException("access_token请求错误，请检查企业微信配置");
                // 请求ticket信息
                Map<String, String> paramsTicket = new HashMap<>();
                paramsTicket.put("access_token", wechatTokenParam.getAccess_token());
                String resTicket = WechatRequest.getMethod(WechatUrlEnum.GET_JSAPI_TICKET.getValue(), params);
                ObjectMapper objectTicket = new ObjectMapper();
                WechatTicketParam wechatTicketParam = objectTicket.readValue(resTicket, WechatTicketParam.class);
                /** 保存token */
                devConfigApi.saveAccessToken(wechatTokenParam.getAccess_token(), EXPIRES_TIME);
                DevWechatUtil.accessToken = wechatTokenParam.getAccess_token();
                /** 保存Ticket */
                devConfigApi.saveTicket(wechatTicketParam.getTicket(), EXPIRES_TIME);
                DevWechatUtil.jsApiTicket = wechatTicketParam.getTicket();
            }
        } catch (Exception e) {
            throw new CommonException(e.getMessage());
        }
    }

    /**
     * 返回加密验证客户端
     * @return
     */
    public static WXBizMsgCrypt getVerifyClient() {
        DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class);
        /* aesKey */
        String aesKey = devConfigApi.getValueByKey(ENCODING_AES_KEY);

        if(ObjectUtil.isEmpty(aesKey)) {
            throw new CommonException("企业微信客户端未正确配置：ENCODING_AES_KEY为空");
        }

        /* token */
        String token = devConfigApi.getValueByKey(WECHAT_TOKEN);

        if(ObjectUtil.isEmpty(token)) {
            throw new CommonException("企业微信客户端未正确配置：WECHAT_TOKEN为空");
        }

        /* CORP_ID */
        String corpId = devConfigApi.getValueByKey(WECHAT_CORP_ID);

        if(ObjectUtil.isEmpty(corpId)) {
            throw new CommonException("企业微信客户端未正确配置：CORP_ID为空");
        }

        try {
            return new WXBizMsgCrypt(token, aesKey, corpId);
        }catch (AesException e){
            logger.error("客户端加密初始化错误：{}", e.getMessage());
            return null;
        }
    }

    /**
     * 企业微信接口，获取子部门ID列表
     *
     * @throws IOException
     */
    public List<Map<String, String>> getDepartment(String parentId) {
        Map<String, String> params = new HashMap<>();
        params.put("access_token", accessToken);
        params.put("id", parentId);
        String res = WechatRequest.getMethod(WechatUrlEnum.GET_DEPARTMENT.getValue(), params);
        logger.info("获取部门--企业微信接口，获取子部门ID列表：{}", res);
        JSONObject jsonObject= JSON.parseObject(res);
        WechatDepartmentRes wechatDepartmentRes = jsonObject.toJavaObject(WechatDepartmentRes.class);
        if(wechatDepartmentRes.getErrcode()!=0) throw new CommonException(wechatDepartmentRes.getErrmsg());
        return wechatDepartmentRes.getDepartment_id();
    }

    /**
     * 企业微信接口，获取部门详情
     *
     * @throws IOException
     */
    public WechatDepartmentRes getDepartmentDetail(String departmentId) {
        Map<String, String> params = new HashMap<>();
        params.put("access_token", accessToken);
        params.put("id", departmentId);
        String res = WechatRequest.getMethod(WechatUrlEnum.GET_DEPARTMENT_DETAIL.getValue(), params);
        logger.info("企业微信接口，获取部门详情--获取部门详情：{}", res);
        JSONObject jsonObject= JSON.parseObject(res);
        return  jsonObject.toJavaObject(WechatDepartmentRes.class);
    }

    /**
     * 企业微信接口，根据组织ID获取 成员
     * @param departId
     */
    public List<Map<String, String>> getUserInfo(String departId) {
        Map<String, String> params = new HashMap<>();
        params.put("access_token", accessToken);
        params.put("department_id", departId);
        String res = WechatRequest.getMethod(WechatUrlEnum.GET_DEPARTMENT_USER.getValue(), params);
        logger.info("企业微信接口，根据组织ID获取 成员--部门成员接口列表：{}", res);
        JSONObject jsonObject= JSON.parseObject(res);
        WechatUserRes wechatUserRes = jsonObject.toJavaObject(WechatUserRes.class);
        return wechatUserRes.getUserlist();
    }

    /**
     * 企业微信接口，用于创建标签
     * @param tagName
     */
    public void createTag(String tagName, String tagId){
        String url = WechatUrlEnum.CREATE_TAG.getValue()+accessToken;
        Map<String, String> params = new HashMap<>();
        params.put("tagname", tagName);
        params.put("tagid", tagId);
        String res = WechatRequest.postMethod(url, params);
        logger.info("企业微信接口，用于创建标签--标签创建结果：{}", res);
    }

    /**
     * 企业微信接口，添加标签用户
     * @param tagId
     * @param userList
     */
    public void addTagUser(String tagId,  List<String> userList){
        String url = WechatUrlEnum.ADD_TAG_USER.getValue()+accessToken;
        WechatTagUserReq req = new WechatTagUserReq();
        req.setTagid(tagId);
        req.setUserlist(userList);
        WechatRequest<WechatTagUserReq> util = new WechatRequest();
        String res = util.postMethod(url, req);
        logger.info("企业微信接口，添加标签用户--用户添加结果：{}", res);
    }

    /**
     * 获取页面js的配置参数
     * @param url
     * @return
     */
    public WechatConfigParam getJsConfig(String url){
        DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class);
        String corpId = devConfigApi.getValueByKey(WECHAT_CORP_ID);
        WechatConfigParam wechatConfigParam = new WechatConfigParam(corpId);
        Instant now = Instant.now();
        long timestamp = now.toEpochMilli();
        String noncestr = CommonStringUtil.generateRandomString(16);
        String enString = "jsapi_ticket="+jsApiTicket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;
        String signature = CommonCryptogramUtil.doSha1Encrypt(enString);
        wechatConfigParam.setUrl(url);
        wechatConfigParam.setTimestamp(timestamp);
        wechatConfigParam.setAppId(corpId);
        wechatConfigParam.setJsapi_ticket(jsApiTicket);
        wechatConfigParam.setSignature(signature);
        return wechatConfigParam;
    }

    /**
     * 获取企业微信用户登录Id
     * @param code
     */
    public String getUserLoginDetail(String code){
        Map<String, String> params = new HashMap<>();
        params.put("code", code);
        String url = WechatUrlEnum.GET_LOGIN_USERINFO.getValue()+accessToken;
        String res = WechatRequest.postMethod(url, params);
        logger.info("获取企业微信用户登录Id--获取的用户微信Id：{}", res);
        JSONObject jsonObject= JSON.parseObject(res);
        Map<String, String> resMap = jsonObject.toJavaObject(Map.class);
        return resMap.get("userid");
    }

    /**
     * 企业微信接口，发送卡片消息
     *
     * @throws IOException
     */
    public String sendCardMessage(List<String> targetList, String content, String url, String targetType) {
        Map<String, String> params = new HashMap<>();
        WechatMessageParam wechatMessageParam = new WechatMessageParam();
        WechatRequest<WechatMessageParam> wechatRequest = new WechatRequest();
        wechatMessageParam.setMsgtype("textcard");
        if(targetType.equals("group")) wechatMessageParam.setTouser(String.join("|", targetList));
        if(targetType.equals("org")) wechatMessageParam.setToparty(String.join("|", targetList));
        params.put("title","活动通知");
        params.put("url",url);
        params.put("btntxt","查看详情");
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日");
        String formattedDate = formatter.format(new Date());
        String des = "<div class=\"gray\">"+formattedDate+"</div>"+"<div class=\"normal\">"+content+"</div>";
        params.put("description",des);
        wechatMessageParam.setTextcard(params);
        wechatMessageParam.setAgentid(AGENT_ID);
        String reqUrl = WechatUrlEnum.SEND_MESSAGE.getValue()+accessToken;
        String res =  wechatRequest.postMethodTemplate(reqUrl,wechatMessageParam);
        JSONObject jsonObject= JSON.parseObject(res);
        WechatDepartmentRes wechatDepartmentRes = jsonObject.toJavaObject(WechatDepartmentRes.class);
        if(wechatDepartmentRes.getErrcode()!=0) throw new CommonException(wechatDepartmentRes.getErrmsg());
        return "success";
    }

    /**
     * 企业微信接口，发送消息
     *
     * @throws IOException
     */
    public String sendMsg(WechatMessageParam devWechatParam){
        WechatRequest<WechatMessageParam> wechatRequest = new WechatRequest();
        devWechatParam.setAgentid(AGENT_ID);
        String reqUrl = WechatUrlEnum.SEND_MESSAGE.getValue()+accessToken;
        String res =  wechatRequest.postMethodTemplate(reqUrl,devWechatParam);
        JSONObject jsonObject= JSON.parseObject(res);
        WechatDepartmentRes wechatDepartmentRes = jsonObject.toJavaObject(WechatDepartmentRes.class);
        if(wechatDepartmentRes.getErrcode()!=0) throw new CommonException(wechatDepartmentRes.getErrmsg());
        return "success";
    }

    /**
     * 企业微信接口，创建日历
     *
     * @throws IOException
     */
    public String addCalendar(WechatCreateCalendarParam param){
        WechatRequest<WechatCreateCalendarParam> wechatRequest = new WechatRequest();
        param.setAgentid(AGENT_ID);
        String reqUrl = WechatUrlEnum.ADD_CALENDAR.getValue()+accessToken;
        String res =  wechatRequest.postMethodTemplate(reqUrl, param);
        JSONObject jsonObject= JSON.parseObject(res);
        WechatCalendarRes response = jsonObject.toJavaObject(WechatCalendarRes.class);
        if(response.getErrcode()!=0) throw new CommonException(response.getErrmsg());
        return response.getCal_id();
    }

    /**
     * 企业微信接口，创建日程
     *
     * @throws IOException
     */
    public String addSchedule( WechatCreateScheduleParam param){
        WechatRequest<WechatCreateScheduleParam> wechatRequest = new WechatRequest();
        param.setAgentid(AGENT_ID);
        String reqUrl = WechatUrlEnum.ADD_SCHEDULE.getValue()+accessToken;
        String res =  wechatRequest.postMethodTemplate(reqUrl, param);
        JSONObject jsonObject= JSON.parseObject(res);
        WechatScheduleRes response = jsonObject.toJavaObject(WechatScheduleRes.class);
        if(response.getErrcode()!=0) throw new CommonException(response.getErrmsg());
        return response.getSchedule_id();
    }

    /**
     * 企业微信接口，创建日程
     *
     * @throws IOException
     */
    public String getUserId(String phone){
        WechatRequest wechatRequest = new WechatRequest<Map<String, String>>();
        String reqUrl = WechatUrlEnum.GET_USERID.getValue()+accessToken;
        Map<String ,String> req = new HashMap<>();
        req.put("mobile", phone);
        String res =  wechatRequest.postMethodTemplate(reqUrl, req);
        JSONObject jsonObject= JSON.parseObject(res);
        Map response = jsonObject.toJavaObject(Map.class);
        if((Integer) response.get("errcode")!=0) throw new CommonException(response.get("errmsg").toString());
        return response.get("userid").toString();
    }
}
